﻿using System;
using System.Collections.Generic;
using System.Xml.Linq;
using System.Xml.XPath;
using System.Security.Cryptography;
using System.Security.Cryptography.Xml;
using System.Xml;
using System.IO;
using HPCloud.Common.Properties;

namespace HPCloud.Objects.DataAccess.Security
{
    public class CredentialListManager
    {
        private Dictionary<string, string> _credentialList = new Dictionary<string, string>();
        static byte[] s_aditionalEntropy                   = { 9, 8, 7, 6, 5 };
        Settings _settings;

//=========================================================================================
/// <summary>
/// 
/// </summary>
//=========================================================================================
        public Settings Settings
        {
            get { return _settings; }
            set { _settings = value; }
        }
//=========================================================================================
/// <summary>
/// 
/// </summary>
/// <param name="settings"></param>
//=========================================================================================
        public CredentialListManager(Settings settings)
        {
            _settings = settings;
        }
//=========================================================================================
/// <summary>
/// 
/// </summary>
/// <param name="serverId"></param>
/// <returns></returns>
//=========================================================================================
        public string GetPassword(string serverId)
        {
            string credentialsFilePath = this.Settings.CredentialListPath;
            File.Decrypt(credentialsFilePath);

            XDocument doc = XDocument.Load(credentialsFilePath);
            XElement credentialNode = doc.XPathSelectElement("//Credential[@serverId='" + serverId + "']");

            if (credentialNode != null)
            {
                File.Encrypt(credentialsFilePath);
                return credentialNode.Attribute("password").Value;
            }
            else
            {
                File.Encrypt(credentialsFilePath);
                return null;
            }
        }
//=========================================================================================
/// <summary>
/// 
/// </summary>
/// <param name="data"></param>
/// <returns></returns>
//=========================================================================================
        public static byte[] Protect(byte[] data)
        {
            try
            {
                // Encrypt the data using DataProtectionScope.CurrentUser. The result can be decrypted 
                //  only by the same current user. 

                return ProtectedData.Protect(data, s_aditionalEntropy, DataProtectionScope.CurrentUser);
            }
            catch (CryptographicException e)
            {
                Console.WriteLine("Data was not encrypted. An error occurred.");
                Console.WriteLine(e.ToString());
                return null;
            }
        }
//=========================================================================================
/// <summary>
/// 
/// </summary>
/// <param name="serverId"></param>
/// <param name="password"></param>
/// <returns></returns>
//=========================================================================================
        public void SetPassword(string serverId, string password)
        {
            string credentialsFilePath = this.Settings.CredentialListPath;

            File.Decrypt(credentialsFilePath);
            XDocument doc = XDocument.Load(credentialsFilePath);
            XElement credentialNode = doc.XPathSelectElement("//Credential[@serverId='" + serverId + "']");

            if (credentialNode != null && password != null && password != String.Empty)
            {
                credentialNode.SetAttributeValue("password", password);
                doc.Save(credentialsFilePath);
            }
            else
            {
                XElement credentialListNode = doc.XPathSelectElement("//CredentialList");
                XElement newCredentialNode  = new XElement("Credential");

                newCredentialNode.Add(new XAttribute("serverId", serverId));
                newCredentialNode.Add(new XAttribute("password", password));
                credentialListNode.Add(newCredentialNode);
                doc.Save(credentialsFilePath);
                File.Encrypt(credentialsFilePath);
            }
        }
    }
}
